package com.fingard.dsp.bank.directbank.lcbip01;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

import com.fingard.constant.Format;
import com.fingard.dsp.bank.directbank.bankInterface.ITransaction;
import com.fingard.dsp.bank.directbank.fngrd01.util.StringHelper;
import com.fingard.dsp.bank.reqrespobj.transaction.Req7515TodayTrans;
import com.fingard.dsp.bank.reqrespobj.transaction.Req7516HisTrans;
import com.fingard.dsp.bank.reqrespobj.transaction.RetAtsTrans;
import com.fingard.dsp.bank.reqrespobj.transaction.detail.RetAtsTransDetail;
import com.fingard.util.DateHelper;
import com.fingard.xml.XElement;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;

/**
 * Created by F on 2018/9/13.
 */
public class LCBIP01Transaction extends LCBIP01Base implements ITransaction {
    /**
     * 历史明细查询
     * @param p_req7516
     * @return
     * @throws Exception
     */
    @Override
    public RetAtsTrans d_7516_HisTrans(Req7516HisTrans p_req7516) throws Exception{
        RetAtsTrans retAtsTrans = new RetAtsTrans(p_req7516.reqHeader);
        retAtsTrans.writeStart();
        String tmpRespCode = "";
        String tmpRespInfo ="";

        try{
            //起始日期
            Calendar tmpCalendarFrom = Calendar.getInstance();
            tmpCalendarFrom.setTime(p_req7516.getDateFrom());
            //结束日期
            Calendar tmpCalendarTo = Calendar.getInstance();
            tmpCalendarTo.setTime(p_req7516.getDateTo());
            //当前日期
            SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMdd");
            Date date=sdf.parse(sdf.format(new Date()));
            Calendar today=Calendar.getInstance();
            today.setTime(date);
            //判断明细类型：今日明细/历史明细
            String flag="0";
            if(tmpCalendarFrom.equals(tmpCalendarTo) && tmpCalendarFrom.equals(today)){
                flag="1";//今日明细
            }
            //校验时间
            if("0".equals(flag)){
                if(!tmpCalendarTo.before(today)){//结束日期不能大于等于自然日
                    tmpRespCode = "-1";
                    tmpRespInfo = "结束日期不能大于等于自然日";
                }
                if(tmpCalendarTo.before(tmpCalendarFrom)){//结束日期必须大于等起始日期
                    tmpRespCode = "-1";
                    tmpRespInfo = "结束日期必须大于等于起始日期";
                }
            }
            int tmpIntDateFrom = 0;
            int tmpIntDateTo = 0;
            while(tmpIntDateFrom<=tmpIntDateTo && StringHelper.isNullOrEmpty(tmpRespCode)){
                Calendar tmpClndrStepTo = Calendar.getInstance();
                tmpClndrStepTo.setTime(tmpCalendarFrom.getTime());
                //当是跨月查询时，先查询起始日期到月末日期记录，再查询月末后一天日期到结束日期记录
                if(DateHelper.compareMonth(tmpCalendarFrom,tmpCalendarTo)==-1){
                    tmpClndrStepTo.set(Calendar.DAY_OF_MONTH,tmpClndrStepTo.getActualMaximum(Calendar.DAY_OF_MONTH));
                }else{
                    tmpClndrStepTo.setTime(tmpCalendarTo.getTime());
                }
                //开始拼接请求报文
                int hasReadNum = 0;
                int totalnum = 0;
                do {
                    XmlTextWriter xmlTextWriter = new XmlTextWriter();
                    LCBIP01Header header = new LCBIP01Header();
                    if ("1".equals(flag)) {
                        header.TuxName = "QueryToday";
                    } else {
                        header.TuxName = "QueryHistory";
                    }
                    header.ReqSeqNo = getQryTransID();
                    writeCommonHeader(xmlTextWriter, header);
                    xmlTextWriter.writeElementString("ReqReserved1", hasReadNum + "");
                    xmlTextWriter.writeElementString("ReqReserved2", "50");
                    xmlTextWriter.writeElementString("ReqReserved3", "");
                    xmlTextWriter.writeElementString("ReqReserved4", "");
                    xmlTextWriter.writeEndElement();
                    XElement body = new XElement("body", "");
                    body.addChild(new XElement("CustCode", bankFront.org));//客户号
                    body.addChild(new XElement("AccNo", p_req7516.actNum));//账号
                    body.addChild(new XElement("AccContry", ""));//账号所属国家。境外户要填写
                    body.addChild(new XElement("AccPriv", ""));//开户行省份
                    body.addChild(new XElement("AccCity", ""));//开户行市
                    body.addChild(new XElement("CurType", convertCurToBank(p_req7516.actCur)));//币种
                    body.addChild(new XElement("StartDate", Format.Date8Format.format(tmpCalendarFrom.getTime())));//起始日期
                    body.addChild(new XElement("EndDate", Format.Date8Format.format(tmpClndrStepTo.getTime())));//结束日期
                    body.addChild(new XElement("ReqReserved1", ""));
                    body.addChild(new XElement("ReqReserved2", ""));
                    body.addChild(new XElement("ReqReserved3", ""));
                    body.addChild(new XElement("ReqReserved4", ""));
                    xmlTextWriter.writeXElement(body);
                    xmlTextWriter.writeEndDocument();

                    //发送请求报文
                    String[] resutlt = sendToBank(xmlTextWriter.toXmlString());
                    //处理响应报文
                    if (resutlt[0].length() == 0) {
                        StringBuilder tmpSbMsg = new StringBuilder();
                        XmlTextReader tmpBkReader = loadBankRespXmlReader(resutlt[1].trim(), tmpSbMsg);
                        if (tmpBkReader != null) {
                            String RespCode = tmpBkReader.getFirstText("/lcbank/head/RespCode");
                            String RespInfo = tmpBkReader.getFirstText("/lcbank/head/RespInfo");
                            //交易成功
                            if ("0".equals(RespCode)) {
                                //获取返回条数
                                String recordNum = tmpBkReader.getFirstText("/lcbank/head/RecordNum");
                                if (Integer.valueOf(recordNum) > 0) {
                                    String respPrvData = tmpBkReader.getFirstText("/lcbank/head/RespPrvData");
                                    String fieldNum = tmpBkReader.getFirstText("/lcbank/head/FieldNum");
                                    //当RecordNum不为0，且respPrvData为空时，读取bill中的报文
                                    if (StringHelper.isNullOrEmpty(respPrvData)) {
                                        //取Bill循环数据的值
                                        //设置遍历计数
                                        int readCount = 0;
                                        while (tmpBkReader.read("/lcbank/body/Bill")) {
                                            XElement readXElement = tmpBkReader.readedXElement;
                                            if(totalnum==0){
                                                totalnum =Integer.valueOf(readXElement.getSingleText("Reserved1").trim());
                                            }
                                            RetAtsTransDetail detail = new RetAtsTransDetail();
                                            detail.actArea = "";//账户区域
                                            detail.actNum = readXElement.getSingleTextNotNull("BankAcc").trim();//银行账号
                                            detail.recAccNum = readXElement.getSingleTextNotNull("TransAcc").trim();//收方银行账号
                                            detail.recAccName = readXElement.getSingleTextNotNull("TransName").trim();//收方账户名称
                                            detail.recAccBank = readXElement.getSingleTextNotNull("TransBankName").trim();//收方银行
                                            detail.tranDate = DateHelper.convertD8toD10(readXElement.getSingleTextNotNull("TransDate").trim());//交易日期
                                            detail.tranTime = detail.tranDate + " " + DateHelper.getFormat8Time(readXElement.getSingleTextNotNull("TransTime").trim());//交易时间
                                            detail.valueDate = detail.tranDate;//起息日，银行没有返回就用tranDate交易日期
                                            detail.tranAmt = readXElement.getSingleTextNotNull("Amt").trim();//交易金额
                                            String cdFlag = readXElement.getSingleTextNotNull("ItemType").trim();//借贷标记 01借付款 02贷收款
                                            if (cdFlag.equals("02")) {
                                                if (detail.tranAmt.indexOf("-") >= 0) {
                                                    detail.cdFlag = "1";
                                                    detail.tranAmt = detail.tranAmt.substring(1);
                                                } else {
                                                    detail.cdFlag = "2";
                                                }
                                            } else if (cdFlag.equals("01")) {
                                                if (detail.tranAmt.indexOf("-") >= 0) {
                                                    detail.cdFlag = "2";
                                                    detail.tranAmt = detail.tranAmt.substring(1);
                                                } else {
                                                    detail.cdFlag = "1";
                                                }
                                            }
                                            detail.accBal = readXElement.getSingleTextNotNull("ITBalance").trim();//账户余额
                                            detail.postTimestamp = "";//时间戳，银行没有就空
                                            detail.billType = "";//单据或票据类型，银行没有就空
                                            detail.billNum = "";//单据或票据号码，银行没有就空
                                            String note = readXElement.getSingleTextNotNull("Remark").trim();
                                            detail.usage = note;//摘要
                                            detail.abstr = pickupAbstr(note);//对账码
                                            detail.payCode = "";//支付码
                                            detail.comment = "";//备注
                                            detail.askNumber = readXElement.getSingleTextNotNull("BusRefNo").trim();//支付流水号
                                            detail.reqBatchNO = "";//支付批号
                                            detail.cur = convertCurToATS(readXElement.getSingleTextNotNull("CurrType").trim());//币种
                                            detail.seqId = "";//序列号
                                            detail.isCollection = "";//是否现金池，银行没有就空
                                            detail.originator = "";//柜员号
                                            detail.busType = readXElement.getSingleTextNotNull("BusType").trim();//新业务类型
                                            detail.urid = readXElement.getSingleTextNotNull("BankSeqNo").trim();//唯一明细号
                                            //detail.accountMark=readXElement.getSingleTextNotNull("Reserved2").trim();//冲账标识  1正常记帐; 2已被冲 3 已抹账
                                            retAtsTrans.writeRetDetail(detail);
                                            readCount++;
                                        }
                                        //查询记录数和遍历数不一致
                                        if (readCount != Integer.valueOf(recordNum)) {
                                            tmpRespCode = "-1";
                                            tmpRespInfo = "统计明细有误";
                                            break;
                                        }
                                        hasReadNum +=readCount;

                                    } else {//否则读取respPrvData中的数据 旧前置返回数据，将废除
                                        String[] count = respPrvData.split("!");
                                        //校验总记录数与实际返回数据是否一致
                                        if (Integer.parseInt(recordNum) != count.length) {
                                            tmpRespCode = "-1";
                                            tmpRespInfo = "返回统计数据与实际数值不一致："+recordNum+" : "+count.length ;
                                            break;
                                        }
                                        //校验数据是否丢失
                                        for (int i = 0; i < count.length; i++) {
                                            String[] num = count[i].split("\\|", -1);
                                            if (Integer.parseInt(fieldNum) != num.length) {
                                                tmpRespCode = "-1";
                                                tmpRespInfo = "返回数据缺失";
                                                break;
                                            }
                                        }
                                        retAtsTrans = readXmlRespPrvData(count, p_req7516, tmpBkReader);
                                    }
                                } else {
                                    tmpRespCode = "0";
                                    tmpRespInfo = "该时间段查询明细记录数为0";
                                    break;
                                }
                            } else {
                                tmpRespCode = "-1";
                                tmpRespInfo = RespInfo;
                                break;
                            }
                        } else {
                            tmpRespCode = "-1";
                            tmpRespInfo = tmpSbMsg.toString();
                            break;
                        }
                    } else {
                        tmpRespCode = "-1";
                        tmpRespInfo = resutlt[1];
                        break;
                    }
                }while (hasReadNum<totalnum);
                if("-1".equals(tmpRespCode)){
                    throw new Exception(tmpRespInfo);
                }
                tmpCalendarFrom = tmpClndrStepTo;
                tmpCalendarFrom.add(Calendar.DAY_OF_MONTH, 1);
                tmpIntDateFrom = Integer.parseInt(Format.Date8Format.format(tmpCalendarFrom.getTime()));
                tmpIntDateTo = Integer.parseInt(Format.Date8Format.format(tmpCalendarTo.getTime()));
            }
        }catch (Exception ex){
            tmpRespCode = "-1";
            tmpRespInfo = ex.getMessage();
            ex.printStackTrace();
        }
        if ("-1".equals(tmpRespCode)) {
            retAtsTrans = new RetAtsTrans(p_req7516.reqHeader);
            retAtsTrans.writeStart();//写返回ATS的统一头部信息
            retAtsTrans.writeRespCode(tmpRespCode);
            retAtsTrans.writeRespInfo(tmpRespInfo);
        }else if(retAtsTrans.getWrittenRdCount() == 0) {
            retAtsTrans.writeRespInfo("交易为空");
            retAtsTrans.writeRespCode("0");
        }
        retAtsTrans.writeEnd();
        return retAtsTrans;
    }

    /**
     * 今日明细查询
     * @param p_req7515
     * @return
     * @throws Exception
     */
    @Override
    public RetAtsTrans d_7515_TodayTrans(Req7515TodayTrans p_req7515) throws Exception{
        Req7516HisTrans p_req7516 = new Req7516HisTrans(p_req7515.reqHeader);
        p_req7516.actArea = p_req7515.actArea;
        p_req7516.actCur = p_req7515.actCur;
        p_req7516.actNum = p_req7515.actNum;
        String date = Format.Date8Format.format(new Date());
        p_req7516.dateFrom = date;
        p_req7516.dateTo = date;
        return d_7516_HisTrans(p_req7516);
    }

    private RetAtsTrans readXmlRespPrvData(String[] readXmlRespPrvData,Req7516HisTrans p_req7516,XmlTextReader tmpBkReader){
        RetAtsTrans retAtsTrans = new RetAtsTrans(p_req7516.reqHeader);
        retAtsTrans.writeStart();
        try{
            for(int i=0;i<readXmlRespPrvData.length;i++){
                String[] count=readXmlRespPrvData[i].split("\\|",-1);
                XElement readXElement = tmpBkReader.readedXElement;
                RetAtsTransDetail detail = new RetAtsTransDetail();
                detail.actArea="";//账户区域
                detail.actNum=count[6].trim();//银行账号
                detail.recAccNum=count[10].trim();//收方银行账号
                detail.recAccName=count[11].trim();//收方账户名称
                detail.recAccBank="";//收方银行
                detail.tranDate=DateHelper.convertD8toD10(count[3].trim());//交易日期
                detail.tranTime=detail.tranDate+ " " + DateHelper.getFormat8Time(count[4].trim());//交易时间
                detail.valueDate=detail.tranDate;//起息日，银行没有返回就用tranDate交易日期
                detail.tranAmt=count[9].trim();//交易金额
                String cdFlag=count[5].trim();//借贷标记 01借付款 02贷收款
                if (cdFlag.equals("02")) {
                    if(detail.tranAmt.indexOf("-")>=0) {
                        detail.cdFlag = "1";
                        detail.tranAmt = detail.tranAmt.substring(1);
                    }else{
                        detail.cdFlag = "2";
                    }
                } else if(cdFlag.equals("01")){
                    if(detail.tranAmt.indexOf("-")>=0){
                        detail.cdFlag = "2";
                        detail.tranAmt = detail.tranAmt.substring(1);
                    }else{
                        detail.cdFlag = "1";
                    }
                }
                detail.accBal=count[7].trim();//账户余额
                detail.postTimestamp="";//时间戳，银行没有就空
                detail.billType="";//单据或票据类型，银行没有就空
                detail.billNum="";//单据或票据号码，银行没有就空
                String note = count[8].trim();
                detail.usage=note;//摘要
                detail.abstr=pickupAbstr(note);//对账码
                detail.payCode="";//支付码
                detail.comment="";//备注
                detail.askNumber=count[13].trim();//支付流水号
                detail.reqBatchNO="";//支付批号
                detail.cur=convertCurToATS(count[2].trim());//币种
                detail.seqId="";//序列号
                detail.isCollection="";//是否现金池，银行没有就空
                detail.originator="";//柜员号
                detail.busType=count[14].trim();//新业务类型
                detail.urid=count[0].trim();//唯一明细号
                //detail.accountMark=readXElement.getSingleTextNotNull("Reserved2").trim();//冲账标识  1正常记帐; 2已被冲 3 已抹账
                retAtsTrans.writeRetDetail(detail);
            }
        }catch (Exception ex){
            ex.printStackTrace();
        }
        return retAtsTrans;
    }
}
